home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UFileHandler.cp < prev    next >
Text File  |  1991-05-01  |  19KB  |  766 lines

  1. // UFileHandler.cp 
  2. /* Copyright © 1984-1991 by Apple Computer Inc.    All rights reserved. */
  3.  
  4. #ifndef __UFILEHANDLER__
  5. #include <UFileHandler.h>
  6. #endif
  7.  
  8. #ifndef __STDIO__
  9. #include <StdIo.h>
  10. #endif
  11.  
  12. #ifndef __GEOMETRY__
  13. #include <Geometry.h>
  14. #endif
  15.  
  16. #ifndef __PACKAGES__
  17. #include <Packages.h>
  18. #endif
  19.  
  20. #ifndef __FOLDERS__
  21. #include <Folders.h>
  22. #endif
  23.  
  24. #ifndef __ERRORS__
  25. #include <Errors.h>
  26. #endif
  27.  
  28. #ifndef __UFILE__
  29. #include <UFile.h>
  30. #endif
  31.  
  32. #ifndef __UAPPLICATION__
  33. #include <UApplication.h>
  34. #endif
  35.  
  36. #ifndef __UFILEBASEDDOCUMENT__
  37. #include <UFileBasedDocument.h>
  38. #endif
  39.  
  40. #ifndef __UMACAPPUTILITIES__
  41. #include <UMacAppUtilities.h>
  42. #endif
  43.  
  44. #ifndef __UERRORMGR__
  45. #include <UErrorMgr.h>
  46. #endif
  47.  
  48. #ifndef __UMACAPPGLOBALS__
  49. #include <UMacAppGlobals.h>
  50. #endif
  51.  
  52. //--------------------------------------------------------------------------------------------------
  53. #pragma segment MAOpen
  54.  
  55. pascal void TFileHandler::Initialize(void)        // override 
  56. {
  57.     inherited::Initialize();
  58.  
  59.     fDocument = NULL;
  60.     fFile = NULL;
  61.     fFileExists = FALSE;
  62.     fHowToSave = svtAskUser;
  63. }
  64.  
  65. //--------------------------------------------------------------------------------------------------
  66. #pragma segment MAOpen
  67.  
  68. pascal void TFileHandler::IFileHandler(TFileBasedDocument* itsDocument,
  69.                                        TFile* itsFile,
  70.                                        const OSType itsFileType,
  71.                                        const OSType itsCreator,
  72.                                        Boolean usesDataFork,
  73.                                        Boolean usesRsrcFork,
  74.                                        Boolean keepsDataOpen,
  75.                                        Boolean keepsRsrcOpen)
  76. {
  77.     FailInfo fi;
  78.  
  79.     VOLATILE(itsFile);
  80.  
  81.     this->IObject();
  82.  
  83.     if (fi.Try())
  84.     {
  85.         if (keepsDataOpen || keepsRsrcOpen)
  86.             fHowToSave = svtAlways;
  87.         else
  88.             fHowToSave = svtAskUser;
  89.  
  90.         if (itsFile)
  91.             itsFile->DefineFile(itsFileType, itsCreator, usesDataFork, usesRsrcFork, keepsDataOpen, keepsRsrcOpen);
  92.         fi.Success();
  93.     }
  94.     else    // Recover
  95.     {
  96.         itsFile = (TFile *)FreeIfObject(itsFile);
  97.         fi.ReSignal();
  98.     }
  99.  
  100.     fFile = itsFile;
  101.     fDocument = itsDocument;
  102. }
  103.  
  104. //--------------------------------------------------------------------------------------------------
  105. #pragma segment MAClose
  106.  
  107. pascal void TFileHandler::Free(void)            // override 
  108. {
  109.     if (fFile)
  110.     {
  111.         this->CloseFile();
  112.         fFile->Free();
  113.         fFile = NULL;
  114.     }
  115.  
  116.     inherited::Free();
  117. }
  118.  
  119. //--------------------------------------------------------------------------------------------------
  120. #pragma segment MAWriteFile
  121.  
  122. pascal void TFileHandler::AboutToSaveFile(CmdNumber itsCmd,
  123.                                           Boolean& makingCopy)
  124. {
  125.     fDocument->AboutToSaveFile(itsCmd, makingCopy);
  126. }
  127.  
  128. //--------------------------------------------------------------------------------------------------
  129. #pragma segment MADocumentRes
  130.  
  131. pascal Boolean TFileHandler::FileAlreadyOpen(TFile* aFile)
  132. {
  133.     if (fFileExists)
  134.         return fFile->IsSameFile(aFile);
  135.     else
  136.         return FALSE;
  137. }
  138.  
  139. //--------------------------------------------------------------------------------------------------
  140. #pragma segment MADocumentRes
  141.  
  142. pascal void TFileHandler::CloseFile(void)
  143. {
  144.     OSErr err;
  145.  
  146.     if (fFile)
  147.         err = fFile->CloseFile(TRUE);
  148. }
  149.  
  150. //--------------------------------------------------------------------------------------------------
  151. #pragma segment MAWriteFile
  152.  
  153. pascal void TFileHandler::DoNeedDiskSpace(long& dataForkBytes,
  154.                                           long& rsrcForkBytes)
  155. {
  156.     fDocument->DoNeedDiskSpace(fFile, dataForkBytes, rsrcForkBytes);
  157.     if (fFile->IsRsrcForkOpen())
  158.         rsrcForkBytes = rsrcForkBytes + kRsrcFileOverhead;
  159. }
  160.  
  161. //--------------------------------------------------------------------------------------------------
  162. #pragma segment MAReadFile
  163.  
  164. pascal void TFileHandler::DoRead(Boolean forPrinting)
  165. {
  166.     fDocument->DoRead(fFile, forPrinting);
  167. }
  168.  
  169. //--------------------------------------------------------------------------------------------------
  170. #pragma segment MAWriteFile
  171.  
  172. pascal void TFileHandler::DoWrite(TFile* aFile,
  173.                                   Boolean makingCopy)
  174. {
  175.     fDocument->DoWrite(aFile, makingCopy);
  176. }
  177.  
  178. //--------------------------------------------------------------------------------------------------
  179. #pragma segment MAFile
  180.  
  181. pascal OSErr TFileHandler::FileChanged(Boolean checkType)
  182. {
  183.     FailInfo fi;
  184.     HParamBlockRec pb;
  185.     OSErr err = noErr;
  186.  
  187.     if (fFileExists)
  188.     {
  189.         if (fi.Try())
  190.         {
  191.             FailOSErr(fFile->GetFileInfo(pb));
  192.             fi.Success();
  193.         }
  194.         else    // Recover
  195.         {
  196.             this->Free();
  197.             fi.ReSignal();
  198.         }
  199.  
  200.         if (checkType && (pb.fileParam.ioFlFndrInfo.fdType != fFile->fFileType))
  201.             err = errFTypeChanged;
  202.         else if (pb.fileParam.ioFlMdDat != fFile->GetModificationDate())
  203.             err = errFileChanged;
  204.     }
  205.     return err;
  206. }
  207.  
  208. //--------------------------------------------------------------------------------------------------
  209. #pragma segment MAFile
  210.  
  211. pascal Boolean TFileHandler::FileExists(void)
  212. {
  213.     return fFileExists;
  214. }
  215.  
  216. //--------------------------------------------------------------------------------------------------
  217. #pragma segment MADocumentRes
  218.  
  219. pascal TFile* TFileHandler::GetFile(void)
  220. {
  221.     return fFile;
  222. }
  223.  
  224. //--------------------------------------------------------------------------------------------------
  225. #pragma segment MADocumentRes
  226.  
  227. pascal void TFileHandler::GetFileName(Str63& aName)
  228. {
  229.     if (fFile)
  230.         fFile->GetName(aName);
  231. }
  232.  
  233. //--------------------------------------------------------------------------------------------------
  234. #pragma segment MAWriteFile
  235.  
  236. pascal Boolean TFileHandler::GetSaveInfo(CmdNumber,
  237.                                          Boolean copyFInfo,
  238.                                          CInfoPBRec& cInfo)
  239. {
  240.     Boolean saveInfo = FALSE;
  241.  
  242.     if (fFileExists && copyFInfo)
  243.     {
  244.         OSErr err = fFile->GetCatInfo(cInfo);
  245.         if (err == noErr)
  246.             saveInfo = TRUE;
  247.     }
  248.     // set the type and creator in case it has changed; the file might be on a file server
  249.     // and someone else could have changed the document 
  250.     cInfo.hFileInfo.ioFlFndrInfo.fdType = fFile->fFileType;
  251.     cInfo.hFileInfo.ioFlFndrInfo.fdCreator = fFile->fCreator;
  252.     return saveInfo;
  253. }
  254.  
  255. //--------------------------------------------------------------------------------------------------
  256. #pragma segment MAFile
  257.  
  258. inline unsigned long __unsigned_long_abs_ (unsigned long a) { return a < 0 ? -a : a; }
  259.  
  260. pascal void TFileHandler::GetTempName(Str63& filename)
  261.  
  262. {
  263.     const short maxName = 31;                    //maximum name size to generate
  264.     const short maxNumber = 10;                    //maximum # digits of the random number
  265.     const short maxPrefix = maxName - maxNumber;
  266.  
  267.     Str255 name;
  268.     short apRefnum;
  269.     Handle apParam;
  270.     unsigned long time;
  271.  
  272.     // If the file is untitled, use the application name.
  273.     fFile->GetName((Str63 &)name);
  274.     if (name.IsEmpty())
  275.         GetAppParms(name, apRefnum, apParam);
  276.     filename = name;
  277.  
  278.     // Check prefix length, and trim it down if too large.
  279.     if (filename.Length() > maxPrefix)
  280.         filename.Length() = (char)maxPrefix;
  281.  
  282.     // Append a pseudo-random number.
  283.     GetDateTime(time);
  284.     NumToString(__unsigned_long_abs_(time ^ (TickCount() >> 16)), name);
  285.     filename += name;
  286.  
  287.     // Check name length, and trim it down if too large.
  288.     if (filename.Length() > maxName)
  289.         filename.Length() = (char)maxName;
  290. }
  291.  
  292. //--------------------------------------------------------------------------------------------------
  293. #pragma segment MAFile
  294.  
  295. pascal Boolean TFileHandler::HasRsrcFork(void)
  296. {
  297.     if (fFile)
  298.         return fFile->HasRsrcFork();
  299.     else
  300.         return FALSE;
  301. }
  302.  
  303. //--------------------------------------------------------------------------------------------------
  304. #pragma segment MAReadFile
  305.  
  306. pascal void TFileHandler::ReadFile(Boolean forPrinting)
  307. {
  308.     FailInfo fi;
  309.  
  310.     if (fFile)
  311.     {
  312.         if (fi.Try())
  313.         {
  314.             FailOSErr(fFile->OpenFile());
  315.  
  316.             fFileExists = TRUE;
  317.  
  318.             this->DoRead(forPrinting);
  319.  
  320.             fi.Success();
  321.         }
  322.         else    // Recover
  323.         {
  324.             this->CloseFile();
  325.             fi.ReSignal();
  326.         }
  327.  
  328.         FailOSErr(fFile->CloseFile(FALSE));
  329.  
  330.         fFile->Modified();                        // Set the modification date 
  331.     }
  332. }
  333.  
  334. //--------------------------------------------------------------------------------------------------
  335. #pragma segment MAWriteFile
  336.  
  337. pascal void TFileHandler::RequestFileName(CmdNumber itsCmdNumber,
  338.                                           Boolean,
  339.                                           TFile* aFile)
  340. {
  341.     StandardFileReply customReply;
  342.     SFReply reply;
  343.     short dlgID;
  344.     Str255 prompt;
  345.     Point dlgLoc;
  346.     ProcPtr dlgHook;
  347.     ProcPtr modalFilter;
  348.     Ptr activeList;
  349.     ProcPtr activateProc;
  350.     Ptr yourDataPtr;
  351.     TDocument * otherDoc;
  352.     Str255 filename;
  353.     Boolean goodReply;
  354.     OSErr err;
  355.  
  356.     aFile->GetName((Str63 &)filename);
  357.     fDocument->SFPutParms(itsCmdNumber, prompt, filename, dlgID, dlgLoc, dlgHook, modalFilter, activeList, activateProc, yourDataPtr);
  358.  
  359. #if qDebug
  360.     gRsrcCheck = 0;                                //force immediate check
  361. #endif
  362.  
  363.     // Update all the windows to avoid a bug in Standard File in which you can't mount a disk
  364.     // correctly when window updates are pending. !!! (Is this still needed?
  365.     gApplication->UpdateAllWindows();
  366.  
  367.     goodReply = FALSE;
  368.  
  369.     if (qNeedsAliasMgr || gConfiguration.hasAliasMgr)
  370.     {
  371.         CustomPutFile(prompt, filename, customReply, dlgID, dlgLoc, (DlgHookYDProcPtr)dlgHook, (ModalFilterYDProcPtr)modalFilter, (short*)activeList, (ActivateYDProcPtr)activateProc, yourDataPtr);
  372.         if (customReply.sfGood)
  373.         {
  374.             aFile->IdentifyWithScript(customReply.sfFile, customReply.sfScript);
  375.             goodReply = TRUE;
  376.         }
  377.     }
  378.     else
  379.     {
  380.         SFPPutFile(dlgLoc, prompt, filename, (DlgHookProcPtr)dlgHook, reply, dlgID, (ModalFilterProcPtr)modalFilter);
  381.         if (reply.good)
  382.         {
  383.             FailOSErr(aFile->IdentifyByTrio(reply.vRefNum, 0, reply.fName));
  384.             goodReply = TRUE;
  385.         }
  386.     }
  387.  
  388.     if (goodReply)
  389.     {
  390.         // See if there is an open document with the same name.    If there is, tell it 
  391.         // we're trying to save it again, which will ordinarily result in failure.
  392.         otherDoc = gApplication->AlreadyOpen(aFile);
  393.         if (otherDoc)
  394.             otherDoc->SaveAgain(itsCmdNumber, fDocument);
  395.  
  396.         // User has already confirmed deleting target in this case, so trash file and get 
  397.         // maximum disk space. 
  398.         err = aFile->DeleteFile();
  399.         if ((err != noErr) && (err != fnfErr))
  400.             Failure(err, 0);
  401.     }
  402.     else
  403.         Failure(noErr, msgCancelled);            // user cancelled 
  404. }
  405.  
  406. //--------------------------------------------------------------------------------------------------
  407. #pragma segment MAWriteFile
  408.  
  409. pascal void TFileHandler::SaveFile(CmdNumber itsCmdNumber,
  410.                                    Boolean askForFilename,
  411.                                    Boolean copyFInfo,
  412.                                    Boolean makingCopy)
  413. {
  414.     FailInfo fi;
  415.     TFile * theSaveFile = NULL;
  416.     long dataBytes = 0;
  417.     long rsrcBytes = 0;
  418.     long neededBlks;
  419.     long usedBlks;
  420.     long freeBlks;
  421.     long blkSize;
  422.     Boolean canSaveInPlace;
  423.     Str255 name;
  424.     OSErr err;
  425.  
  426.     VOLATILE(theSaveFile);
  427.     VOLATILE(askForFilename);
  428.     VOLATILE(makingCopy);
  429.  
  430.     if (fi.Try())
  431.     {
  432.         theSaveFile = NewFile();
  433.  
  434.         if (askForFilename)
  435.             this->RequestFileName(itsCmdNumber, makingCopy, theSaveFile);
  436.         else
  437.             theSaveFile->IdentifyByFile(fFile);
  438.  
  439.         theSaveFile->DefineFile(fFile->fFileType, fFile->fCreator, fFile->fUsesDataFork, fFile->fUsesRsrcFork, FALSE, FALSE);
  440.         theSaveFile->SetPermissions(fsRdWrPerm, fsRdWrPerm);// Since we intend to write to it 
  441.  
  442.         this->AboutToSaveFile(itsCmdNumber, makingCopy);
  443.  
  444.         // Get information about the volume saving to 
  445.         FailOSErr(theSaveFile->GetFreeBlocks(freeBlks));
  446.         
  447.         // Don't fill the disk completely.
  448.         freeBlks--;
  449.  
  450.         // compute size needed to save document 
  451.         FailOSErr(theSaveFile->GetBlockSize(blkSize));
  452.  
  453.         this->DoNeedDiskSpace(dataBytes, rsrcBytes);
  454.         neededBlks = NumBlocks(rsrcBytes, blkSize) + NumBlocks(dataBytes, blkSize);
  455.  
  456.         // If there is enough space we're done.  Save the file by the method specified 
  457.         if (freeBlks >= neededBlks)
  458.         {
  459.             if ((fHowToSave == svtAskUser) || (fHowToSave == svtAlways))
  460.                 this->SaveViaTemp(itsCmdNumber, makingCopy, copyFInfo, theSaveFile);
  461.             else
  462.                 this->SaveInPlace(itsCmdNumber, makingCopy, copyFInfo, theSaveFile);
  463.         }
  464.         // Is there enough space to save the file in place? 
  465.         else
  466.         {
  467.             canSaveInPlace = FALSE;                // Default value 
  468.  
  469.             // See if we can save in place be recovering the space used by the existing file 
  470.             err = theSaveFile->GetPhysicalSize(dataBytes, rsrcBytes);
  471.             if (err == noErr)
  472.             {
  473.                 usedBlks = NumBlocks(dataBytes, blkSize) + NumBlocks(rsrcBytes, blkSize);
  474.  
  475.                 if (neededBlks <= usedBlks + freeBlks)
  476.                 {
  477.                     // Saving in place purges the existing file.  Should we ask before going ahead? 
  478.                     if ((fHowToSave == svtAskUser) || (fHowToSave == sipAskUser))
  479.                     {
  480.                         theSaveFile->GetName((Str63 &)name);
  481.                         ParamText(name, "", "", "");
  482.                         if (MacAppAlert(phPurgeOld, NULL) == kYesButton)
  483.                             canSaveInPlace = TRUE;
  484.                         else
  485.                             Failure(noErr, msgCancelled);
  486.                     }
  487.                     else if (fHowToSave == sipAlways)
  488.                         canSaveInPlace = TRUE;
  489.                 }
  490.             }
  491.             // If no file to recover space from, signal disk full error.  Otherwise just display error 
  492.             else if (err != fnfErr)
  493.                 Failure(err, 0);
  494.  
  495.             if (canSaveInPlace)
  496.                 this->SaveInPlace(itsCmdNumber, makingCopy, copyFInfo, theSaveFile);
  497.             else
  498.                 Failure(dskFulErr, 0);
  499.         }
  500.  
  501. #if qDebugMsg
  502.         err = theSaveFile->GetPhysicalSize(dataBytes, rsrcBytes);
  503.         if (err == noErr)
  504.         {
  505.             usedBlks = NumBlocks(dataBytes, blkSize) + NumBlocks(dataBytes, blkSize);
  506.             if (usedBlks != neededBlks)
  507.             {
  508.                 fprintf(stderr, "In TFileHandler.Save: DoNeedDiskSpace estimated disk space incorrectly.\n");
  509.                 fprintf(stderr, "estimated # disk blocks = %ld\n", neededBlks);
  510.                 fprintf(stderr, "   actual # disk blocks = %ld\n", usedBlks);
  511.             }
  512.         }
  513. #endif
  514.  
  515.         if (!makingCopy)
  516.         {
  517.             theSaveFile->GetName((Str63 &)name);
  518.             fDocument->FileHasBeenSaved(name);
  519.  
  520.             fFileExists = TRUE;
  521.             fFile->IdentifyByFile(theSaveFile);
  522.             fFile->Modified();
  523.             FailOSErr(fFile->OpenFile());
  524.         }
  525.  
  526.         fi.Success();
  527.     }
  528.     else    // Recover
  529.     {
  530.         long newMsg;
  531.  
  532.         if (theSaveFile)
  533.         {
  534.             err = theSaveFile->FlushVolume();
  535.             if (fi.message == 0)
  536.                 theSaveFile->GetName((Str63 &)gErrorParm3);
  537.             theSaveFile = (TFile *)FreeIfObject(theSaveFile);
  538.         }
  539.  
  540.         if (!askForFilename)
  541.             newMsg = msgSaveFailed;
  542.         else if (makingCopy)
  543.             newMsg = msgSaveCopyFailed;
  544.         else
  545.             newMsg = msgSaveAsFailed;
  546.  
  547.         FailNewMessage(fi.error, fi.message, newMsg);
  548.         fi.ReSignal();
  549.     }
  550.  
  551.     err = theSaveFile->FlushVolume();
  552.  
  553.     theSaveFile->Free();
  554. }
  555.  
  556. //--------------------------------------------------------------------------------------------------
  557. #pragma segment MAWriteFile
  558.  
  559. pascal void TFileHandler::SaveInPlace(CmdNumber itsCmdNumber,
  560.                                       Boolean makingCopy,
  561.                                       Boolean copyFInfo,
  562.                                       TFile* itsFile)
  563. {
  564.     FailInfo fi;
  565.     CInfoPBRec cInfo;
  566.     Boolean validInfo;
  567.     OSErr err;
  568.  
  569.     VOLATILE(itsFile);
  570.     VOLATILE(validInfo);
  571.     VOLATILE(makingCopy);
  572.  
  573.     validInfo = this->GetSaveInfo(itsCmdNumber, copyFInfo, cInfo);
  574.  
  575.     this->CloseFile();                                // close the file 
  576.  
  577.     err = fFile->DeleteFile();
  578.     if ((err != noErr) && (err != fnfErr))
  579.         Failure(err, 0);
  580.  
  581.     if (fi.Try())
  582.     {
  583.         FailOSErr(itsFile->CreateFile());
  584.  
  585.         if (validInfo)                            // Change attributes of itsFile?
  586.             FailOSErr(itsFile->SetCatInfo(cInfo));
  587.  
  588.         FailOSErr(itsFile->OpenFile());
  589.  
  590.         this->DoWrite(itsFile, makingCopy);
  591.  
  592.         fi.Success();
  593.     }
  594.     else    // Recover
  595.     {
  596.         OSErr err;
  597.  
  598.         err = itsFile->CloseFile(TRUE);
  599. #if qDebugMsg
  600.         if (err != noErr)
  601.             fprintf(stderr, "In HdlMkNewCopy: error from itsFile.CloseFile is %d\n", err);
  602. #endif
  603.  
  604.         err = itsFile->DeleteFile();
  605. #if qDebugMsg
  606.         if ((err != noErr) && (err != fnfErr))
  607.             fprintf(stderr, "In HdlMkNewCopy: error from itsFile.DeleteFile is %d\n", err);
  608. #endif
  609.  
  610.         fi.ReSignal();
  611.     }
  612.  
  613.     FailOSErr(itsFile->CloseFile(TRUE));
  614. }
  615.  
  616. //--------------------------------------------------------------------------------------------------
  617. #pragma segment MAWriteFile
  618.  
  619. pascal void TFileHandler::SaveViaTemp(CmdNumber itsCmdNumber,
  620.                                       Boolean makingCopy,
  621.                                       Boolean copyFInfo,
  622.                                       TFile* itsFile)
  623. {
  624.     FailInfo fi;
  625.     Boolean validInfo;
  626.     CInfoPBRec cInfo;
  627.     FSSpec saveFileSpec;
  628.     Str63 tmpName;
  629.     short tmpVRefNum;
  630.     long tmpDirID;
  631.     OSErr err;
  632.  
  633.     VOLATILE(itsFile);
  634.     VOLATILE(makingCopy);
  635.     
  636.     validInfo = this->GetSaveInfo(itsCmdNumber, copyFInfo, cInfo);
  637.  
  638.     itsFile->GetFileSpec(saveFileSpec);        // Save file spec since it may be clobbered 
  639.  
  640.     this->GetTempName(tmpName);
  641.  
  642.     // If we are using the folder manager, put in the temporary folder, creating if necessary 
  643.     if (qNeedsFolderMgr || gConfiguration.hasFolderMgr)
  644.     {
  645.         FailOSErr(FindFolder(saveFileSpec.vRefNum, kTemporaryFolderType, kCreateFolder, tmpVRefNum, tmpDirID));
  646.         FailOSErr(itsFile->IdentifyByTrio(tmpVRefNum, tmpDirID, tmpName));
  647.     }
  648.     else
  649.         itsFile->SetName(tmpName);
  650.  
  651.     if (fi.Try())
  652.     {
  653.         FailOSErr(itsFile->CreateFile());
  654.  
  655.         if (validInfo)                            // Change attributes of itsFile??
  656.             FailOSErr(itsFile->SetCatInfo(cInfo));
  657.         FailOSErr(itsFile->OpenFile());
  658.  
  659.         this->DoWrite(itsFile, makingCopy);
  660.  
  661.         fi.Success();
  662.     }
  663.     else    // Recover
  664.     {
  665.         OSErr err;
  666.  
  667.         err = itsFile->CloseFile(TRUE);
  668. #if qDebugMsg
  669.         if (err != noErr)
  670.             fprintf(stderr, "In HdlMkNewCopy: error from CloseFile is %d", err);
  671. #endif
  672.  
  673.         err = itsFile->DeleteFile();
  674. #if qDebugMsg
  675.         if ((err != noErr) && (err != fnfErr))
  676.             fprintf(stderr, "In HdlMakeCopy: error from itsFile.DeleteFile is %d", err);
  677. #endif
  678.  
  679.     }
  680.  
  681.     FailOSErr(itsFile->CloseFile(TRUE));
  682.  
  683.     if (!makingCopy)
  684.         this->CloseFile();                            // Close the documents file 
  685.  
  686.     if (fi.Try())
  687.     {
  688.         if (qNeedsFolderMgr || gConfiguration.hasFolderMgr)
  689.         {
  690.             if (fFileExists && copyFInfo)
  691.             {
  692.                 // Exchange the existing file for the one in the temporary folder… 
  693.                 FailOSErr(itsFile->ExchangeFiles(fFile));
  694.  
  695.                 // and delete the one left in the temporary folder 
  696.                 err = itsFile->DeleteFile();
  697.                 if ((err != noErr) && (err != fnfErr))
  698.                     Failure(err, 0);
  699.             }
  700.             else                                // The temp file was created in the temporary directory.  Move it back where it belongs 
  701.                 FailOSErr(itsFile->MoveAndRename(saveFileSpec));
  702.         }
  703.         else
  704.         {
  705.             itsFile->SetName(saveFileSpec.name);// Set to original name…
  706.             err = itsFile->DeleteFile();        // and delete it if it exists…
  707.             if ((err != noErr) && (err != fnfErr))
  708.                 Failure(err, 0);
  709.                 
  710.             itsFile->SetName(tmpName);            // and set it back for renaming
  711.             FailOSErr(itsFile->RenameFile(saveFileSpec.name));
  712.         }
  713.  
  714.         // Identify the file again since it may have changed if it was saved in a temporary folder 
  715.         itsFile->Identify(saveFileSpec);
  716.  
  717.         fi.Success();
  718.     }
  719.     else    // Recover
  720.     {
  721.         FailInfo newfi;
  722.  
  723.         if (fFileExists &&!makingCopy)
  724.         {
  725.             if (newfi.Try())
  726.             {
  727.                 FailOSErr(fFile->OpenFile());
  728.                 newfi.Success();
  729.             }
  730.             else    // Recover
  731.             {
  732.                 // If reopen attempt fails, make sure original error gets through.
  733.                 Failure(newfi.error, newfi.message);
  734.                 newfi.ReSignal();
  735.             }
  736.         }
  737.         fi.ReSignal();
  738.     }
  739.  
  740. }
  741.  
  742. //--------------------------------------------------------------------------------------------------
  743. #pragma segment MADocumentRes
  744.  
  745. pascal void TFileHandler::SetFileName(const Str63& aName)
  746. {
  747.     if (fFile)
  748.         fFile->SetName(aName);
  749. }
  750.  
  751. //--------------------------------------------------------------------------------------------------
  752. #pragma segment MAFields
  753.  
  754. pascal void TFileHandler::Fields(TObject* obj)
  755. {
  756.     obj->DoToField("TFileHandler", (Ptr)NULL, bClass);
  757.     obj->DoToField("fDocument", (Ptr) & fDocument, bObject);
  758.     obj->DoToField("fFile", (Ptr) & fFile, bObject);
  759.     obj->DoToField("fFileExists", (Ptr) & fFileExists, bBoolean);
  760.     obj->DoToField("fHowToSave", (Ptr) & fHowToSave, bByte);
  761.  
  762.     inherited::Fields(obj);
  763. }
  764.  
  765.  
  766.